package client

import (
	"encoding/json"

	"gitee.com/sdxstar/air/logger"
	"gitee.com/sdxstar/air/protocol"
)

type Context interface {
	IsClosed() bool
	Close()

	Emit(event string, v interface{}) error
	Ack(event string, v interface{}, r interface{}) error

	Content() []byte
	Packet() protocol.Packet
	Bind(v interface{}) error

	Reply(v interface{}) error

	Logger() logger.Logger
}

type context struct {
	client *Client
	p      protocol.Packet
}

func newContext(client *Client, p protocol.Packet) Context {
	return &context{
		client: client,
		p:      p,
	}
}

func (c *context) Reply(v interface{}) error {
	if v == nil {
		rp := c.p.NewReplyPacket(nil)
		return c.client.reply(rp)
	}
	msg, err := c.client.opts.Codec.Encode(v)
	if err != nil {
		return err
	}
	rp := c.p.NewReplyPacket(msg)
	return c.client.reply(rp)
}

func (c *context) Packet() protocol.Packet {
	return c.p
}

func (c *context) Bind(v interface{}) error {
	return json.Unmarshal(c.p.Body(), v)
}

func (c *context) Content() []byte {
	return c.p.Body()
}

func (c *context) IsClosed() bool {
	return c.client.IsClosed()
}

func (c *context) Close() {
	c.client.Close()
}

func (c *context) Emit(event string, v interface{}) error {
	return c.client.Emit(event, v)
}

func (c *context) Ack(event string, v interface{}, r interface{}) error {
	return c.client.Ack(event, v, r)
}

func (c *context) Logger() logger.Logger {
	return c.client.log
}
